package com.xyauto.uilibx.colorpicker;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.NinePatchDrawable;
import android.graphics.drawable.ScaleDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.util.SparseArray;

import java.util.Objects;

/**
 * created by gongziyi on 2024/7/9 11:10
 */
public class BitColor {
    // 色彩参数
    private ColorParams mColorParams;
    // 局部缓存
    private final SparseArray<CacheParams> mCacheMap = new SparseArray<>();


    private final boolean isList;
    private final boolean supportGradient;
    private final Context context;

    public BitColor(Context context, boolean isList) {
        this(context, isList, false);
    }

    public BitColor(Context context, boolean isList, boolean supportGradient) {
        this.context = context;
        this.isList = isList;
        this.supportGradient = supportGradient;
    }

    public Drawable createDrawable(Drawable drawable, int defaultLayer, int angle, int[] color, int[] supportState) {
        if (drawable instanceof BitmapDrawable) {
            drawable = createBitmapDrawable((BitmapDrawable) drawable, defaultLayer, angle, color);
        } else if (drawable instanceof StateListDrawable) {
            drawable = createStateDrawable((StateListDrawable) drawable, defaultLayer, angle, supportState);
        } else if (drawable instanceof LayerDrawable) {
            drawable = createLayerDrawable((LayerDrawable) drawable, defaultLayer, angle, supportState);
        }
        return drawable;
    }

    public Drawable createBitmapDrawable(BitmapDrawable drawable, int defaultLayer, int angle, int[] color) {
        if (color == null) color = getColorArray(defaultLayer);
        Drawable cacheDrawable = findCacheDrawable(drawable, color, angle);
        if (cacheDrawable == null) {
            cacheDrawable = createBitmapDrawable(drawable, color, angle);
            saveCacheDrawable(drawable, cacheDrawable, color, angle);
        }
        return cacheDrawable;
    }

    public Drawable createStateDrawable(StateListDrawable drawable, int defaultLayer, int angle, int[] supportState) {
        StateListDrawable newList = new StateListDrawable();
        for (int i = 0; i < drawable.getStateCount(); i++) {
            int[] stateSet = drawable.getStateSet(i);
            Drawable stateDrawable = drawable.getStateDrawable(i);
            if (containAttr(stateSet, supportState) || stateDrawable instanceof StateListDrawable) {
                stateDrawable = createDrawable(stateDrawable, defaultLayer, angle, getColorArray(defaultLayer), supportState);
            }
            newList.addState(stateSet, stateDrawable);
        }
        return newList;
    }

    public Drawable createLayerDrawable(LayerDrawable drawable, int defaultLayer, int angle, int[] supportState) {
        LayerDrawable mdrawable;
        int count = drawable.getNumberOfLayers();
        if (count <= 0) return drawable;
        Drawable[] layers = new Drawable[count];
        for (int i = 0; i < count; i++) {
            Drawable target = drawable.getDrawable(i);
            int index = BitmapColorHelper.getLayerIndex(drawable.getId(i));
            if (target instanceof ScaleDrawable&&((ScaleDrawable) target).getDrawable()instanceof GradientDrawable){
                int[] arr=new int[2];
                if (containAttr(target.getState(), supportState) ){
                    arr[0]=getColorArray(defaultLayer)[0];
                    arr[1]=getColorArray(defaultLayer)[1];
                }else {
                    arr[0]=getColorArray(defaultLayer)[0];
                    arr[1]=getColorArray(defaultLayer)[0];
                }
                // ((GradientDrawable)((ScaleDrawable) drawable).getDrawable()).setOrientation(GradientDrawable.Orientation.LEFT_RIGHT);
                ((GradientDrawable)((ScaleDrawable) target).getDrawable()).setColors(arr);
            }
            if (target instanceof ScaleDrawable&& index != -1){
                if (((ScaleDrawable) target).getDrawable() instanceof BitmapDrawable){
                    ((ScaleDrawable) target).setDrawable(createDrawable((((ScaleDrawable) target).getDrawable()), defaultLayer, angle, getColorArray(index), supportState))  ;

                }
            }

            if (index != -1) {
                target = createDrawable(target, defaultLayer, angle, getColorArray(index), supportState);
            }
            layers[i] = target;
        }
        mdrawable=new LayerDrawable(layers);
        for (int i = 0; i < count; i++) {
            mdrawable.setLayerHeight(i, drawable.getLayerHeight(i));
            mdrawable.setLayerGravity(i, drawable.getLayerGravity(i));
        }
        return mdrawable;
    }


    public Drawable createBitmapDrawable(BitmapDrawable drawable, int[] colorArray, int angle) {
        if (colorArray != null && colorArray.length > 0) {
            //差距用于计算是否为纯色 即第0位与其他色相同
            if (supportGradient && isGradient(colorArray)) {
                Bitmap bitmap = drawable.getBitmap();

                int centerWidth = drawable.getIntrinsicWidth() >> 1;
                int centerHeight = drawable.getIntrinsicHeight() >> 1;

                double radian = Math.toRadians(angle);

                int centerX = (int) (centerWidth * Math.cos(radian));
                int centerY = (int) (centerHeight * Math.sin(radian));

                // 计算开始位置的x和y坐标
                int startX = centerWidth - centerX;
                int startY = centerHeight + centerY;

                // 计算结束位置的x和y坐标
                int endX = centerWidth + centerX;
                int endY = centerHeight - centerY;

                bitmap = BitmapColorHelper.createBitmap(bitmap,
                        new LinearGradient(startX, startY, endX, endY, colorArray, null, Shader.TileMode.MIRROR));
                return new BitmapDrawable(context.getResources(), bitmap);
            } else {
                drawable.setColorFilter(colorArray[0], PorterDuff.Mode.SRC_ATOP);
            }
        }
        return drawable;
    }

    public boolean containAttr(int[] stateSet, int[] attrs) {
        if (attrs == null) return true;
        for (int attr : attrs) {
            for (int state : stateSet) {
                if (state == attr) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean isGradient(int[] colorArray) {
        for (int color : colorArray) {
            if (colorArray[0] != color) return true;
        }
        return false;
    }

    /**
     * 读取颜色对象，并解析
     *
     * @param params 颜色对象
     * @return 是否有改变
     */
    public boolean loadColorParams(ColorParams params) {
        if (!Objects.equals(mColorParams, params)) {
            mColorParams = params;
            return true;
        }
        return false;
    }

    public boolean hasColorParams() {
        return mColorParams != null;
    }


    /**
     * 获取颜色数组
     *
     * @param layerIndex 层指针
     * @return 三色渐变组
     */
    public int[] getColorArray(int layerIndex) {
        if (mColorParams != null) {
            return mColorParams.getLayerColor(layerIndex);
        } else {
            return new int[BitmapColorHelper.getGradientSize()];
        }
    }


    /**
     * 获取缓存数组
     *
     * @return 缓存列表
     */
    public SparseArray<CacheParams> getCacheMap() {
        //如果是列表使用全局缓存，如果不是列表则使用view自身缓存
        return isList ? BitmapColorHelper.getCacheMap() : mCacheMap;
    }

    /**
     * 查找缓存
     *
     * @param drawable   原始drawable
     * @param colorArray 对应变色
     * @param angle      角度
     * @return 变色drawable
     */
    public Drawable findCacheDrawable(Drawable drawable, int[] colorArray, int angle) {
        Drawable.ConstantState state = drawable.getConstantState();
        if (state != null) {
            CacheParams params = getCacheMap().get(state.hashCode());
            if (params != null && !params.isChange(colorArray, angle)) {
                return params.getDrawable();
            }
        }
        return null;
    }


    /**
     * 保存缓存
     *
     * @param oldDrawable 原始drawable
     * @param newDrawable 变色drawable
     * @param colorArray  对应变色
     * @param angle       角度
     */
    public void saveCacheDrawable(Drawable oldDrawable, Drawable newDrawable, int[] colorArray, int angle) {
        Drawable.ConstantState state = oldDrawable.getConstantState();
        if (state != null) {
            getCacheMap().put(state.hashCode(), new CacheParams(newDrawable, colorArray, angle));
        }
    }

}
